//#define BLYNK_DEBUG
#define BLYNK_PRINT stdout
#ifdef RASPBERRY
  #include <BlynkApiWiringPi.h>
#else
  #include <BlynkApiLinux.h>
#endif
#include <BlynkSocket.h>
#include <BlynkOptionsParser.h>

static BlynkTransportSocket _blynkTransport;
BlynkSocket Blynk(_blynkTransport);
#include <BlynkWidgets.h>

static const char *auth, *serv;
static uint16_t port;

int setTemp1 = 30,setTemp2 = 25, feedFlag = 0, feedHold = 10;
long HX711_Buffer = 0;
long Weight_Maopi = 0,Weight_Shiwu = 0;
float Weight = 0;
FILE *stream1, *stream2, *stream3, *stream4;
#include <sys/types.h>
#include <sys/stat.h> 
#include <sys/sysinfo.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <iostream>
#include <wiringPi.h>
#include <pthread.h>
#include <vector>
#include <time.h>
#include <string>
#include <sstream>
#include "ds1302.h"
#include "ds1302.c"
using namespace std;

#define BUFSIZE 128
#define pinPWM 13
#define HX711_SCK 27  //这根是绿线
#define HX711_DT 17	//需要遵循BCM编码方式，如果在wiringPI目录下则另外遵循wifingpi
#define GapValue 445

unsigned long HX711_Read(void)  //增益128
{
  unsigned long count; 
  unsigned char i;
  bool Flag = 0;

  digitalWrite(HX711_DT, HIGH);
  delayMicroseconds(1);

  digitalWrite(HX711_SCK, LOW);
  delayMicroseconds(1);

    count=0; 
    while(digitalRead(HX711_DT)); 
    for(i=0;i<24;i++)
  { 
      digitalWrite(HX711_SCK, HIGH); 
    delayMicroseconds(1);
      count=count<<1; 
    digitalWrite(HX711_SCK, LOW); 
    delayMicroseconds(1);
      if(digitalRead(HX711_DT))
      count++; 
  } 
  digitalWrite(HX711_SCK, HIGH); 
  count ^= 0x800000;
  delayMicroseconds(1);
  digitalWrite(HX711_SCK, LOW); 
  delayMicroseconds(1);
  
  return(count);
}
void Init_Hx711()
{
  pinMode(HX711_SCK, OUTPUT); 
  pinMode(HX711_DT, INPUT);
}
void Get_Maopi()
{
  Weight_Maopi = HX711_Read();    
} 
long Get_Weight()
{
  HX711_Buffer = HX711_Read();
  Weight_Shiwu = HX711_Buffer;
  Weight_Shiwu = Weight_Shiwu - Weight_Maopi;       //
  Weight_Shiwu = (long)((float)Weight_Shiwu/GapValue);  
  return Weight_Shiwu;
}
// Register defines
#define	RTC_SECS	 0
#define	RTC_MINS	 1
#define	RTC_HOURS	 2
#define	RTC_DATE	 3
#define	RTC_MONTH	 4
#define	RTC_DAY		 5
#define	RTC_YEAR	 6
#define	RTC_WP		 7
#define	RTC_TC		 8
#define	RTC_BM		31
static unsigned int masks [] = { 0x7F, 0x7F, 0x3F, 0x3F, 0x1F, 0x07, 0xFF } ;
struct setTime
{
	int hour;
	int min;
};
setTime morning =
{
	7,
	0
};
setTime noon =
{
	12,
	0
};
setTime afternoon =
{
	18,
	0
};
BLYNK_WRITE(V0)
{
    printf("Got a value: %s\n", param[0].asStr());
}
BLYNK_WRITE(V2)
{
	setTemp1 = param.asInt();
    //printf("Got a value: %d\n", param.asInt());
}
BLYNK_WRITE(V3)
{
	setTemp2 = param.asInt();	
	//printf("Got a value: %s\n", param[0].asStr());
}

WidgetLED led1(V5);
WidgetLED led2(V6);
WidgetLED morningLED(V31);
WidgetLED noonLED(V32);
WidgetLED afternoonLED(V33);
WidgetLED startLED(V41);
WidgetLED stopLED(V42);
WidgetLED takeLED(V43);
WidgetLED sendLED(V44);

BLYNK_WRITE(V11) {
  TimeInputParam t(param);
  // Process start time
  if (t.hasStartTime())
  {
	morning.hour = t.getStartHour();
	morning.min = t.getStartMinute();
	printf("morning ok\n");
  }
  else
  {
    // Do nothing
  }
}
BLYNK_WRITE(V12) {
  TimeInputParam t(param);
  // Process start time
  if (t.hasStartTime())
  {
	noon.hour = t.getStartHour();
	noon.min = t.getStartMinute();
	printf("noon ok\n");
  }
  else
  {
    // Do nothing
  }
}
BLYNK_WRITE(V13) {
  TimeInputParam t(param);
  // Process start time
  if (t.hasStartTime())
  {
	afternoon.hour = t.getStartHour();
	afternoon.min = t.getStartMinute();
	printf("afternoon ok\n");
  }
  else
  {
    // Do nothing
  }
}
BLYNK_WRITE(V46)	//完美执行开启相机与关闭相机指令
{
	if(param.asInt())
	{
		stream1 = popen("raspivid -o - -t 0 -vf -hf -fps 20 -b 500000 | ffmpeg -re -ar 44100 -ac 2 -acodec pcm_s16le -f s16le -ac 2 -i /dev/zero -f h264 -i - -vcodec copy -acodec aac -ab 128k -g 50 -strict experimental -f flv rtmp://203.195.199.109:1935/live/fzucloud", "w");
	}
	else
	{
		//kill(0, SIGINT);
		system("killall ffmpeg");
		pclose(stream1);
	}
}
BLYNK_WRITE(V47)
{
	if(param.asInt())
	{
		stream2 = popen("sudo shutdown -h now", "w");
	}	
	else
	{
		pclose(stream2);
	}
}
BLYNK_WRITE(V48)
{
	if(param.asInt() == 1)
	{
		stream3 = popen("raspistill -t 2000 -o image.jpg", "w");
	}
	else
	{
		pclose(stream3);
	}
}
BLYNK_WRITE(V49)
{
	if(param.asInt() == 1)
	{
		stream4 = popen("python sendemail.py", "w");
	}
	else
	{
		pclose(stream4);
	}
}

/*
 * bcdToD:
 *	BCD decode/encode
 *********************************************************************************
 */
static int bcdToD (unsigned int byte, unsigned int mask)
{
  unsigned int b1, b2 ;
  byte &= mask ;
  b1 = byte & 0x0F ;
  b2 = ((byte >> 4) & 0x0F) * 10 ;
  return b1 + b2 ;
}
void readTemp()
{
	float temp;
	int i, j;
    int fd;
	int ret;
	int keepfan;
	char buf[BUFSIZE];
	char tempBuf[5];
	fd = open("/sys/bus/w1/devices/28-0416c43c57ff/w1_slave", O_RDONLY);
	ret = read(fd, buf, BUFSIZE);
	for(i=0;i<sizeof(buf);i++){
		if(buf[i] == 't'){
			for(j=0;j<sizeof(tempBuf);j++)
				tempBuf[j] = buf[i+2+j]; 				
			}	
		}
	temp = (float)atoi(tempBuf) / 1000;
	if(temp > setTemp1) {
		digitalWrite(5, HIGH);
		digitalWrite(6, LOW);
		keepfan = 1;
	}
	else {
		if(keepfan == 1)
		{
			digitalWrite(5, HIGH);
			digitalWrite(6, LOW);
		}
	}
	if(temp < setTemp2) {
		digitalWrite(5, LOW);
		digitalWrite(6, LOW);
		keepfan = 0;
	}
	Blynk.virtualWrite(V1, temp);
	//printf("%.3f C\n",temp);
	//sleep(0.25);		
	close(fd);	
}
void readDepth()
{
	int keeppump = 0;
	if(digitalRead(23) == 0)
	{
		Blynk.virtualWrite(V4, 0);
		digitalWrite(7, HIGH);
		digitalWrite(8, LOW);
		keeppump = 1;
	}
	else 
	{
		Blynk.virtualWrite(V4, 1);
		if(keeppump == 1)
		{
			digitalWrite(7, HIGH);
			digitalWrite(8, LOW);
		}
	}
	if(digitalRead(24) == 1)
	{
		Blynk.virtualWrite(V4, 2);
		digitalWrite(7, LOW);
		digitalWrite(8, LOW);
		keeppump = 0;
	}
}
void readTime()
{
	int k;
	int clock [8] ;
	int iTos [8];
	//string iTos [8], qq = "";
	//stringstream ss [8];
	ds1302setup (17, 27, 22) ;	//这里管脚17，27，22，然而wiringPi中使用0，1，2
    ds1302clockRead (clock) ;
	while(clock [6] != 24)
		ds1302clockRead (clock) ;
	//printf("%d\n", clock [6]);
	for(k = 0; k <=6; k++)
	{
		iTos [k] = bcdToD (clock [k], masks [k]);
	}
	Blynk.virtualWrite(V26, 2000 + iTos [6]);
	Blynk.virtualWrite(V24, iTos[4]);
	Blynk.virtualWrite(V23, iTos[3]);
	Blynk.virtualWrite(V22, iTos[2]);
	Blynk.virtualWrite(V21, iTos[1]);
	Blynk.virtualWrite(V20, iTos[0]);
	// lcd.print(0, 0, 2000 + iTos [6]);
	// lcd.print(4, 0, "/");
	// lcd.print(5, 0, iTos [4]);
	// lcd.print(7, 0, "/");
	// lcd.print(8, 0, iTos [3]);
	// lcd.print(0, 1, iTos [2]);
	// lcd.print(2, 1, ":");
	// lcd.print(3, 1, iTos [1]);
	// lcd.print(5, 1, ":");
	// lcd.print(6, 1, iTos [0]);
	if(feedFlag == 1)	//	进入喂食阶段
	{
		if(iTos [0] <= feedHold)
		{
			digitalWrite(20, HIGH);
			digitalWrite(21, LOW);
		}
		else
		{
			digitalWrite(20, LOW);
			digitalWrite(21, LOW);
			feedFlag = 0;
		}
	}
	else	//	没有的话，进入此处进行判断
	{
	if(iTos [2] < noon.hour)	//	这是早上
	{
		Blynk.virtualWrite(V34, 1);
		if(morning.hour == iTos [2])
		{
			if(morning.min == iTos [1])
			{
				feedFlag = 1;
				morningLED.on();
			}
			else
			{
				morningLED.off();
			}
		}
	}
	if(iTos [2] == noon.hour)
	{
		Blynk.virtualWrite(V34, 0);
		if(iTos [1] == noon.min)
		{
			feedFlag = 1;
			noonLED.on();
		}
		else
		{
			noonLED.off();
		}
	}
	if(iTos [2] >= noon.hour)	//	这是早上
	{
		Blynk.virtualWrite(V34, 2);
		if(afternoon.hour == iTos [2])
		{
			if(afternoon.min == iTos [1])
			{
				feedFlag = 1;
				afternoonLED.on();
			}
			else
			{
				afternoonLED.off();
			}
		}
	}
	}
	//terminal.println("ok time");
	//sleep(0.25);	//比较稳定，休眠1s	
}
void readWeight()
{
	Weight = Get_Weight();	//计算放在传感器上的重物重量
	// printf("%f", float(Weight));	//串口显示重量
	// printf(" g\n");	//显示单位
	// printf("\n");		//显示单位
	// delay(1000);				//延时1s
	Blynk.virtualWrite(V30, Weight);
}
PI_THREAD(readAll)
{
	Init_Hx711();				//初始化HX711模块连接的IO设置
	delay(1000);
	Get_Maopi();		//获取毛皮
	while(true)
	{
		while(digitalRead(16) == 1)
		{
			readTemp();
			readDepth();	
		}


		// printf("meet\n");
		readWeight();

	}
}

void setup()
{
	//int startTime = mills();	//设定开始的时间
	wiringPiSetup () ;	
	piThreadCreate(readAll);	//创建线程，只能额外创建一个线程
	pinMode(5, OUTPUT);
	pinMode(6, OUTPUT);
	pinMode(7, OUTPUT);
	pinMode(8, OUTPUT);
	pinMode(20, OUTPUT);
	pinMode(21, OUTPUT);
	pinMode(26, OUTPUT);
	pinMode(23, INPUT);
	pinMode(24, INPUT);
	pinMode(16, INPUT);
	//pinMode(pinPWM, PWM_OUTPUT);
    Blynk.begin(auth, serv, port);
}

void loop()
{
    Blynk.run();
}


int main(int argc, char* argv[])
{
    parse_options(argc, argv, auth, serv, port);

    setup();
    while(true) {
        loop();
    }

    return 0;
}
